
package com.joysuch.wwyt.core.service.impl;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import com.joysuch.wwyt.core.bean.FileConvertResult;
import com.joysuch.wwyt.core.service.FileConvertor;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;
import org.jodconverter.core.office.OfficeException;
import org.jodconverter.core.office.OfficeUtils;
import org.jodconverter.local.JodConverter;
import org.jodconverter.local.office.LocalOfficeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope(value = "singleton")
public class JodOfficeToPdfFileConvertor implements FileConvertor {

    private static final Logger logger = LoggerFactory.getLogger(JodOfficeToPdfFileConvertor.class);
    private List<String> suffixes = Arrays.asList("doc", "docx", "xls", "xlsx", "ppt", "pptx");

    @Value("${wwyt.convertor.libreoffce.home}")
    private String libreOfficeHome;

    private LocalOfficeManager manager;

    @Value("${jodconverter.portNumbers}")
    private String portsStr;

    public boolean supportFormat(String fromFormat, String toFormat) {
        return suffixes.contains(fromFormat.toLowerCase()) && "pdf".equalsIgnoreCase(toFormat);
    }

    @PostConstruct
    public void init() {
        //默认2002
        int[] portNumbers={2002};
        if (StringUtils.isNotBlank(portsStr)) {
            String[] ports = portsStr.split(",");
            portNumbers = Arrays.stream(ports).mapToInt(Integer::valueOf).toArray();
        }
        String officeHome = libreOfficeHome;
        if (StringUtils.isBlank(officeHome)) {
            officeHome = System.getProperty("office.home");
        }
        manager = LocalOfficeManager.builder().officeHome(officeHome).taskExecutionTimeout(1000 * 1000L).install().portNumbers(portNumbers).taskQueueTimeout(1000000L).maxTasksPerProcess(1000)
                .build();
        try {
            manager.start();
            logger.info("LibreOffice转换服务启动成功");
        } catch (OfficeException e) {
            logger.error("LibreOffice启动失败，将无法进行文件转换", e);
        }
    }

    @PreDestroy
    public void destroy() {
        OfficeUtils.stopQuietly(manager);
    }

    public FileConvertResult convert(File fromFile, File toFile) {
        long start = System.currentTimeMillis();
        try {
            logger.info("start~ convert {} to {}\n", fromFile.getAbsolutePath(), toFile.getAbsolutePath());
            // 执行转换
            JodConverter.convert(fromFile).to(toFile).execute();
            logger.info("jod convert finished {}\n", toFile.getAbsolutePath());

            FileConvertResult result = new FileConvertResult();
            result.setConvertFile(toFile);
            result.setConvertFileSize((int) toFile.length());
            // 提取封面图片
            String coverImagePath = coverImagePath(toFile);
            logger.info("start extract cover {}\n", coverImagePath);
            int pages = extractCoverImage(toFile, coverImagePath);
            logger.info("cover extract success {}\n", coverImagePath);
            result.setCoverImageFile(new File(coverImagePath));
            long end = System.currentTimeMillis();
            result.setConvertCostTime((int) (end - start));
            result.setPages(pages);
            logger.info("cost {} ms for file {}\n", end - start, fromFile.getAbsolutePath());
            return result;
        } catch (Exception cex) {
            logger.error("转换文件" + fromFile.getAbsolutePath() + "出错", cex);
        } finally {
        }
        return null;
    }

    private String coverImagePath(File file) {
        return file.getParent() + File.separator + FilenameUtils.getBaseName(file.getName()) + "_0.jpg";
    }

    private int extractCoverImage(File pdfFile, String coverPath) {
        try {
            // 如果资源目录存在
            // 调用jar包
            PDDocument document;
            try {
                document = PDDocument.load(pdfFile);
            } catch (IOException e) {
                e.printStackTrace();
                throw new Exception("加载pdf文件出错：可能的原因是文件路径不正确或者文件过大");
            }
            PDPageTree list = document.getDocumentCatalog().getPages();
            PDFRenderer pdfRenderer = new PDFRenderer(document);
            int pageCounter = 0;
            try {
                if (list.getCount() == 0) {
                    return 0;
                }
                BufferedImage bim = pdfRenderer.renderImageWithDPI(pageCounter, 300, ImageType.RGB);
                boolean flag = ImageIOUtil.writeImage(bim, coverPath, 300);
                if (!flag) {
                    logger.error("保存封面出错");
                }
                document.close();
                logger.info("保存封面成功");
                return list.getCount();
            } catch (IOException e) {
                logger.error("提取封面出错", e);
            }
        } catch (Exception e) {
            logger.error("提取封面出错", e);
        }
        return 0;
    }

    /**
     * 测试main方法
     *
     * @param args
     */
    public static void main(String[] args) {
        JodOfficeToPdfFileConvertor convert = new JodOfficeToPdfFileConvertor();
        convert.convert(new File(args[0]), new File(args[1]));
    }

}
